import axios from 'axios'
import store from '@/store'
import { Message } from 'element-ui'
import router from '@/router'
import qs from 'qs'

const request = axios.create({})

function refreshToken () {
  return axios.create()({
    method: 'POST',
    url: '/front/user/refresh_token',
    data: qs.stringify({
      // refreshtoken 只能使用一次
      refreshtoken: store.state.user.refresh_token
    })
  })
}

// 请求拦截器
request.interceptors.request.use(function (config) {
  const { user } = store.state
  if (user && user.access_token) {
    config.headers.Authorization = user.access_token
  }
  return config
}, function (error) {
  return Promise.reject(error)
})

// 响应拦截器
let isRefreshing = false // 控制刷新 token 的状态
let requests: any = [] // 存储刷新 token 期间过来的 401 请求
request.interceptors.response.use(function (response) {
  return response
}, async function (error) {
  if (error.response) { // 请求收到响应，但是状态码超出 2xx
    const { status } = error.response
    if (status === 400) {
      Message.error('请求参数错误')
    } else if (status === 401) {
      // 无token，token无效，token过期
      if (!store.state.user) {
        router.push({ name: 'login', query: { redirect: router.currentRoute.fullPath } })
        return Promise.reject(error)
      }

      if (!isRefreshing) {
        // 尝试获取新的token
        isRefreshing = true // 开启刷新状态
        return refreshToken().then(res => {
          if (!res.data.success) {
            throw new Error('刷新 Token 失败')
          }
          // 成功， 把失败的请求重新发出去
          store.commit('setUser', res.data.content)
          // 把 requests 队列中的请求重新发出去
          requests.forEach((cb: () => any) => cb())
          requests = []
          return request(error.config)
        }).catch(() => {
          // 失败，清除当前用户状态, 跳转回登录页
          store.commit('setUser', null)
          router.push({ name: 'login', query: { redirect: router.currentRoute.fullPath } })
          return Promise.reject(error)
        }).finally(() => {
          isRefreshing = false // 重置刷新状态
        })
      }

      // 刷新状态下，把请求挂起，放到 requests 中
      return new Promise(resolve => {
        requests.push(() => {
          resolve(request(error.config))
        })
      })
    } else if (status === 403) {
      Message.error('没有权限，请联系管理员')
    } else if (status === 404) {
      Message.error('请求资源不存在')
    } else if (status >= 500) {
      Message.error('服务端错误,请联系管理员')
    }
  } else if (error.request) { // 请求发出去，但是没有收到响应（请求超时，网络中断）
    Message.error('请求超时, 请刷新重试')
  } else { // 在设置请求时发生了一些事情，触发了一个错误
    Message.error(`请求失败: ${error.messsage}`)
  }
  return Promise.reject(error)
})

export default request
